/*
 * Copyright 2009 eBusinessInformation
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.excilys.ymca.view;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import roboguice.inject.ContextScoped;
import android.content.Context;
import android.util.Log;
import android.widget.SimpleAdapter;

import com.excilys.ymca.R;
import com.excilys.ymca.command.Command;
import com.google.inject.Inject;

/**
 * Cette classe a en charge la construction de la liste de maps qui sera fournie
 * à un SimpleAdapter. Notez qu'à chaque élément de la liste est associée une
 * commande (implémentation de Command) à effectuer en cas de sélection de
 * l'élément correspondant. Une fois la méthode build() appelée sur une instance
 * de {@link #ContactSimpleAdapterBuilderAndCommandInvoker(Context)}, il n'est
 * plus possible d'ajouter d'actions.
 * 
 * @author Pierre-Yves Ricau ( py.ricau+ymca @ gmail.com )
 * 
 */
@ContextScoped
public class ContactSimpleAdapterBuilderAndCommandInvoker {

	/**
	 * Marqueur pour les logs.
	 */
	private static final String				TAG				= ContactSimpleAdapterBuilderAndCommandInvoker.class.getSimpleName();

	/**
	 * Liste permettant de construire le SingleAdapter.
	 */
	private ArrayList<Map<String, String>>	adapterData		= new ArrayList<Map<String, String>>();

	/**
	 * Liste de commandes à exécutées. L'ordre des commandes est le même que les
	 * éléments de adapterData.
	 */
	private ArrayList<Command>				contactCommands	= new ArrayList<Command>();

	private final static String				TITLE_KEY		= "title";

	private final static String				CONTENT_KEY		= "content";

	/**
	 * Marqueur permettant d'empêcher l'ajout d'actions une fois que l'adapter a
	 * été construit.
	 */
	private boolean							built			= false;

	private final Context					context;

	@Inject
	public ContactSimpleAdapterBuilderAndCommandInvoker(Context context) {
		this.context = context;
	}

	/**
	 * Ajoute une action dans le builder. Le titre et le contenu seront deux
	 * lignes différentes affichées dans l'élément de la liste. La commande est
	 * l'action à effectuer lorsque l'élément sera sélectionné dans la liste.
	 * 
	 * @param title
	 * @param content
	 * @param command
	 */
	public void addAction(String title, String content, Command command) {

		/*
		 * On empêche l'ajout d'actions une fois la liste construite.
		 */
		if (built) {
			throw new UnsupportedOperationException("List already built");
		}

		HashMap<String, String> actionData = new HashMap<String, String>();
		actionData.put(TITLE_KEY, title);
		actionData.put(CONTENT_KEY, content);
		adapterData.add(actionData);
		contactCommands.add(command);
	}

	/**
	 * Construit le SimpleAdapter à partir des différentes actions ajoutées. Une
	 * fois la méthode {@link #build()} appelée, il n'est plus possible
	 * d'appeler la méthode {@link #addAction(String, String, Command)}.
	 * 
	 * @return
	 */
	public SimpleAdapter build() {
		built = true;

		String[] from = new String[] { TITLE_KEY, CONTENT_KEY };

		int[] to = new int[] { R.id.item_title, R.id.item_content };

		/*
		 * On envoie au SimpleAdapter les données associées à la liste,
		 * l'identifiant du layout à utiliser pour construire chaque élément de
		 * la liste, un tableau contenant les clés des hashmap contenant les
		 * données, et pour finir un tableau contenant les identifiants de vues
		 * associés à ces données.
		 */
		return new SimpleAdapter(context, adapterData, R.layout.contact_list_item, from, to);
	}

	/**
	 * Exécute la Command correspondant à la position de l'action correspondante
	 * dans l'adapter.
	 * 
	 * @param position
	 */
	public void execute(int position) {
		if (position >= 0 && position < contactCommands.size()) {
			Command command = contactCommands.get(position);
			if (command != null) {
				command.execute();
			}
		} else {
			Log.e(TAG, "No command found for position " + position);
		}
	}

}
